﻿using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

using Anmlz.Model.Model;
using Anmlz.Services;

namespace Anmlz.Web.Controllers
{
    using System.Linq;

    using Anmlz.Data.Contracts;
    using Anmlz.Model.Entities;
    using Anmlz.Services.Contracts;

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class BreedsController : BaseApiController
    {
        private readonly IConfigService _configService;
        private readonly IFileNameService _fileNameService;
        private readonly IBreedImageTypeService _breedImageTypeService;

        public BreedsController(IUnitOfWork unitOfWork,
            IModelFactory modelFactory,
            IConfigService configService,
            IFileNameService fileNameService,
            IBreedImageTypeService breedImageTypeService)
            : base(unitOfWork, modelFactory)
        {
            _configService = configService;
            _fileNameService = fileNameService;
            _breedImageTypeService = breedImageTypeService;
        }

        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        public HttpResponseMessage PostImage(int id, string imageType, [FromBody]ImageModel model)
        {
            try
            {
                if (!(!string.IsNullOrWhiteSpace(model.Url) &&
                      _fileNameService.IsImageExtensionValid(model.Url) &&
                      _breedImageTypeService.IsTypeValid(imageType)))
                {
                    return Request.CreateResponse(HttpStatusCode.BadRequest);
                }

                var breedEntity = UnitOfWork.Breeds.GetById(id);
                if (breedEntity == null)
                {
                    return Request.CreateResponse(HttpStatusCode.BadRequest);
                }

                using (var client = new WebClient())
                {
                    model.Name = _fileNameService.GetUniqueFileName(model.Url);
                    var imagePath = _fileNameService.GetPathForSavingImage(model.Name);
                    client.DownloadFile(model.Url, imagePath);
                }

                using (var tran = UnitOfWork.DbContext.Database.BeginTransaction())
                {
                    try
                    {
                        var imageEntity = ModelFactory.Parse(model);
                        if (!UnitOfWork.Images.Insert(imageEntity))
                        {
                            tran.Rollback();
                            return Request.CreateResponse(HttpStatusCode.BadRequest);
                        }

                        var type = _breedImageTypeService.GetImageType(imageType);
                        switch (type)
                        {
                            case BreedImageType.Adult:
                                breedEntity.BreedAdultImageId = imageEntity.Id;
                                break;
                            case BreedImageType.Pet:
                                breedEntity.BreedPetImageId = imageEntity.Id;
                                break;
                        }

                        if (!UnitOfWork.Breeds.Update(breedEntity))
                        {
                            tran.Rollback();
                            return Request.CreateResponse(HttpStatusCode.BadRequest);
                        }
                        UnitOfWork.Save();
                        tran.Commit();
                        return Request.CreateResponse(HttpStatusCode.Created, ModelFactory.Create(imageEntity));
                    }
                    catch
                    {
                        tran.Rollback();
                    }
                }
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
            catch
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
        }

        public HttpResponseMessage Post([FromBody]BreedModel model)
        {
            using (var tran = UnitOfWork.DbContext.Database.BeginTransaction())
            {
                try
                {
                    var entity = ModelFactory.Parse(model, true);

                    if (!(UnitOfWork.Breeds.Insert(entity) && UnitOfWork.Save()))
                    {
                        tran.Rollback();
                        return Request.CreateResponse(HttpStatusCode.BadRequest);
                    }

                    // temperaments
                    if (model.CreatureTemperaments != null && model.CreatureTemperaments.Any())
                    {
                        foreach (var temperamentModel in model.CreatureTemperaments)
                        {
                            CreatureTemperament temperamentEntity = null;
                            temperamentEntity = temperamentModel.Id == 0
                                ? this.UnitOfWork.GetCreatureTemperamentByName(temperamentModel.Name)
                                : this.UnitOfWork.CreatureTemperaments.All.FirstOrDefault(
                                    ct => ct.Id == temperamentModel.Id);

                            if (temperamentEntity == null)
                            {
                                temperamentEntity = ModelFactory.Parse(temperamentModel, true);
                                temperamentEntity.CreatureTypeId = entity.CreatureTypeId;
                                if (
                                    !(UnitOfWork.CreatureTemperaments.Insert(temperamentEntity) && UnitOfWork.Save()))
                                {
                                    tran.Rollback();
                                    return Request.CreateResponse(HttpStatusCode.BadRequest);
                                }
                            }

                            if (!UnitOfWork.BreedToCreatureTemperaments.Insert(
                                new BreedToCreatureTemperament
                                {
                                    BreedId = entity.Id,
                                    CreatureTemperamentId = temperamentEntity.Id
                                }))
                            {
                                tran.Rollback();
                                return Request.CreateResponse(HttpStatusCode.BadRequest);
                            }

                        }
                    }

                    // colors
                    if (model.CreatureColors != null && model.CreatureColors.Any())
                    {
                        foreach (var colorModel in model.CreatureColors)
                        {
                            CreatureColor colorEntity = null;
                            colorEntity = colorModel.Id == 0
                                ? this.UnitOfWork.GetCreatureColorByName(colorModel.Name)
                                : this.UnitOfWork.CreatureColors.All.FirstOrDefault(ct => ct.Id == colorModel.Id);

                            if (colorEntity == null)
                            {
                                colorEntity = ModelFactory.Parse(colorModel, true);
                                colorEntity.CreatureTypeId = entity.CreatureTypeId;
                                if (!(UnitOfWork.CreatureColors.Insert(colorEntity) && UnitOfWork.Save()))
                                {
                                    tran.Rollback();
                                    return Request.CreateResponse(HttpStatusCode.BadRequest);
                                }
                            }

                            if (!UnitOfWork.BreedToCreatureColors.Insert(
                                new BreedToCreatureColor()
                                {
                                    BreedId = entity.Id,
                                    CreatureColorId = colorEntity.Id
                                }))
                            {
                                tran.Rollback();
                                return Request.CreateResponse(HttpStatusCode.BadRequest);
                            }

                        }

                    }

                    // characteristics
                    if (model.CreatureCharacteristics != null && model.CreatureCharacteristics.Any())
                    {
                        foreach (var characteristicModel in model.CreatureCharacteristics)
                        {
                            CreatureCharacteristic characteristicEntity =
                                UnitOfWork.CreatureCharacteristics.All.FirstOrDefault(
                                    ct => ct.Id == characteristicModel.Id);

                            // characteristic doesn't exist in base. it's wrong
                            if (characteristicEntity == null)
                            {
                                tran.Rollback();
                                return Request.CreateResponse(HttpStatusCode.BadRequest);
                            }

                            if (!UnitOfWork.BreedToCreatureCharacteristics.Insert(
                                new BreedToCreatureCharacteristic()
                                {
                                    BreedId = entity.Id,
                                    CreatureCharacteristicId = characteristicEntity.Id
                                }))
                            {
                                tran.Rollback();
                                return Request.CreateResponse(HttpStatusCode.BadRequest);
                            }

                        }
                    }

                    UnitOfWork.Save();
                    tran.Commit();
                    return Request.CreateResponse(HttpStatusCode.Created, ModelFactory.Create(entity));
                }
                catch
                {
                    tran.Rollback();
                }
            }


            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }
    }
}
